package com.gjy.util.basic;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-06-19 14:22:12
 */
public class JsonFieldFinder {

    private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    private static List<Object> results; // 存储所有匹配值

    // 查找所有同名字段的值（返回List）
    public static List<Object> findFields(String json, String fieldName) {
        results = new ArrayList<>();
        JsonElement root = gson.fromJson(json, JsonElement.class);
        findFieldRecursive(root, fieldName, true); // 递归搜索
        return results;
    }

    // 递归搜索实现
    private static void findFieldRecursive(JsonElement element, String fieldName, boolean caseSensitive) {
        if (element == null || element.isJsonNull()) return;

        // 处理JSON对象：检查当前层字段 + 递归子对象
        if (element.isJsonObject()) {
            JsonObject obj = element.getAsJsonObject();
            for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                String key = entry.getKey();
                JsonElement value = entry.getValue();

                // 字段名匹配则收集值
                boolean isMatch = caseSensitive ?
                        key.equals(fieldName) : key.equalsIgnoreCase(fieldName);
                if (isMatch) {
                    addResult(value); // 添加匹配值到结果集
                }
                // 递归搜索子节点
                findFieldRecursive(value, fieldName, caseSensitive);
            }
        }

        // 处理JSON数组：遍历每个元素递归搜索
        if (element.isJsonArray()) {
            for (JsonElement item : element.getAsJsonArray()) {
                findFieldRecursive(item, fieldName, caseSensitive);
            }
        }
    }

    // 解析值并存入结果集
    private static void addResult(JsonElement value) {
        if (value.isJsonPrimitive()) {
            results.add(value.getAsJsonPrimitive()); // 字符串/数字/布尔值
        } else {
            results.add(value); // 对象或数组
        }
    }

    // 查找字段的值（返回Object类型）
    public static Object findField(String json, String fieldName) {
        return findField(gson.fromJson(json, JsonElement.class), fieldName, true);
    }

    // 查找字段的值（返回指定类型）
    public static <T> T findField(String json, String fieldName, Class<T> type) {
        Object result = findField(json, fieldName);
        return result != null ? gson.fromJson(gson.toJsonTree(result), type) : null;
    }

    // 递归查找实现
    private static Object findField(JsonElement element, String fieldName, boolean caseSensitive) {
        if (element == null || element.isJsonNull()) {
            return null;
        }

        // 如果是JSON对象，查找字段
        if (element.isJsonObject()) {
            JsonObject obj = element.getAsJsonObject();
            String matchKey = null;

            // 检查是否有直接匹配的字段
            for (String key : obj.keySet()) {
                boolean matches = caseSensitive ?
                        key.equals(fieldName) : key.equalsIgnoreCase(fieldName);

                if (matches) {
                    matchKey = key;
                    break;
                }
            }

            // 如果找到匹配键，返回其值
            if (matchKey != null) {
                JsonElement value = obj.get(matchKey);
                return value.isJsonPrimitive() ?
                        value.getAsJsonPrimitive() : value;
            }

            // 递归搜索子对象
            for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
                Object result = findField(entry.getValue(), fieldName, caseSensitive);
                if (result != null) {
                    return result;
                }
            }
        }

        // 如果是JSON数组，遍历数组元素
        if (element.isJsonArray()) {
            for (JsonElement item : element.getAsJsonArray()) {
                Object result = findField(item, fieldName, caseSensitive);
                if (result != null) {
                    return result;
                }
            }
        }

        return null;
    }

}
